﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Globalization;

using RSEngine;
using RSEngine.Core;

namespace RS.UI
{
    /// <summary>
    /// Interaction logic for Hierarchy.xaml
    /// </summary>
    public partial class Hierarchy : UserControl
    {

        #region Constructor

        public Hierarchy()
        {
            InitializeComponent();

            Engine.SceneUpdated += new SceneUpdateEventHandler(Engine_SceneUpdated);
        }

        #endregion

        #region Engine_SceneUpdated

        void Engine_SceneUpdated(RSEngine.Core.RSBase source, SceneUpdateAction action)
        {
            if (source is Scene && action == SceneUpdateAction.Reset)
            {
                Dispatcher.BeginInvoke(
                    DispatcherPriority.Send,
                    new Action(delegate()
                        {
                            OnResetScene();
                        })
                    );
            }
        }

        #endregion

        #region OnResetScene

        private void OnResetScene()
        {
            tree.Items.Clear();

            foreach (Layer layer in Engine.Scene.Layers)
            {
                TreeViewItem LayerItem = CreateTreeViewItem(layer, "dtLayer");
                tree.Items.Add(LayerItem);

                foreach (Camera camera in layer.Cameras)
                {
                    TreeViewItem cameraItem = GenerateCamera(camera);
                    LayerItem.Items.Add(cameraItem);
                }

                foreach (LightSource light in layer.Lights)
                {
                    TreeViewItem lightItem = GenerateLight(light);
                    LayerItem.Items.Add(lightItem);
                }

                foreach (Node node in layer.Nodes)
                {
                    TreeViewItem nodeItem = GenerateNode(node);
                    LayerItem.Items.Add(nodeItem);
                }

                foreach (RSEngine.Core.Geometry geometry in layer.Geometries)
                {
                    TreeViewItem geometryItem = GenerateGeometry(geometry);
                    LayerItem.Items.Add(geometryItem);
                }
            }
        }

        #endregion

        #region GenerateCamera

        private TreeViewItem GenerateCamera(Camera camera)
        {
            return CreateTreeViewItem(camera, "dtCamera");
        }

        #endregion

        #region GenerateLight

        private TreeViewItem GenerateLight(LightSource light)
        {
            return CreateTreeViewItem(light, "dtLight");
        }

        #endregion

        #region GenerateNode

        private TreeViewItem GenerateNode(Node node)
        {
            TreeViewItem item = CreateTreeViewItem(node, "dtNode");

            foreach (Camera child in node.Cameras)
            {
                TreeViewItem cameraItem = GenerateCamera(child);
                item.Items.Add(cameraItem);
            }

            foreach (LightSource child in node.Lights)
            {
                TreeViewItem lightItem = GenerateLight(child);
                item.Items.Add(lightItem);
            }

            foreach (Node child in node.Children)
            {
                TreeViewItem childItem = GenerateNode(child);
                item.Items.Add(childItem);
            }

            foreach (RSEngine.Core.Geometry child in node.Geometries)
            {
                TreeViewItem childItem = GenerateGeometry(child);
                item.Items.Add(childItem);
            }

            return item;
        }

        #endregion

        #region GenerateGeometry

        private TreeViewItem GenerateGeometry(RSEngine.Core.Geometry geometry)
        {
            TreeViewItem item = CreateTreeViewItem(geometry, "dtGeometry");

            foreach (RSEngine.Core.Geometry child in geometry.Children)
            {
                TreeViewItem childItem = GenerateGeometry(child);
                item.Items.Add(childItem);
            }

            return item;
        }

        #endregion

        #region CreateTreeViewItem

        private TreeViewItem CreateTreeViewItem(RSBase rsBase, string template)
        {
            TreeViewItem item = new TreeViewItem();

            Grid grid = (Grid)LoadTemplate(template);

            TextBlock text = (TextBlock)grid.FindName("txtName");
            text.Text = rsBase.Name;

            Image icon = (Image)grid.FindName("imgIsVisible");
            icon.MouseUp += new MouseButtonEventHandler(IsVisible_MouseUp);

            icon = (Image)grid.FindName("imgIsLocked");
            icon.MouseUp += new MouseButtonEventHandler(IsLocked_MouseUp);

            item.Header = grid;

            item.Tag = rsBase;

            return item;
        }

        private FrameworkElement LoadTemplate(string key)
        {
            DataTemplate template = (DataTemplate)FindResource(key);
            return (FrameworkElement)template.LoadContent();
        }

        #endregion

        #region Event : IsVisible / IsLocked

        void IsVisible_MouseUp(object sender, MouseButtonEventArgs e)
        {
            Image icon = (Image)sender;
            TreeViewItem item = (TreeViewItem)((FrameworkElement)icon.Parent).Parent;
            Transformable renderable = item.Tag as Transformable;
            renderable.IsVisible = !renderable.IsVisible;

            if (renderable.IsVisible)
                icon.Source = new BitmapImage(new Uri("pack://application:,,,/images/hierarchy/visibleOn.png", UriKind.RelativeOrAbsolute));
            else
                icon.Source = new BitmapImage(new Uri("pack://application:,,,/images/hierarchy/visibleOff.png", UriKind.RelativeOrAbsolute));

            Engine.NotifySceneUpdated(renderable, SceneUpdateAction.Update);
        }

        void IsLocked_MouseUp(object sender, MouseButtonEventArgs e)
        {
            Image icon = (Image)sender;
            TreeViewItem item = (TreeViewItem)((FrameworkElement)icon.Parent).Parent;
            Transformable renderable = item.Tag as Transformable;
            renderable.IsLocked = !renderable.IsLocked;

            if (renderable.IsLocked)
                icon.Source = new BitmapImage(new Uri("pack://application:,,,/images/hierarchy/lockOn.png", UriKind.RelativeOrAbsolute));
            else
                icon.Source = new BitmapImage(new Uri("pack://application:,,,/images/hierarchy/lockOff.png", UriKind.RelativeOrAbsolute));

            Engine.NotifySceneUpdated(renderable, SceneUpdateAction.Update);
        }

        #endregion

        #region COMMENTED

        //item.DataContext = layer;
        //item.HeaderTemplate = (DataTemplate)FindResource("dtLayer");

        //DataTemplate template = (DataTemplate)FindResource("dtLayer");
        ////item.HeaderTemplate = template;
        //DependencyObject dep = template.LoadContent();

        //item.Header = dep;

        //Binding binding = new Binding();
        //binding.Source = layer.Name;
        //binding.ElementName = "Name";
        //binding.Converter = new NameConverter();
        //BindingOperations.SetBinding(dep, FrameworkElement.DataContextProperty, binding);

        //Binding binding = new Binding();
        //binding.Source = layer;
        //item.SetBinding(FrameworkElement.DataContextProperty, binding);
        //BindingOperations.SetBinding(item, FrameworkElement.DataContextProperty, binding);

        //---- Set up the data binding
        //Binding binding = new Binding();
        //binding.Source = data;
        //BindingOperations.SetBinding(element, FrameworkElement.DataContextProperty, binding);

        #endregion

    }

}
